package com.ruoyi.system.util;

import cn.hutool.core.util.RandomUtil;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.Assert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.AUser;
import com.ruoyi.system.mapper.AUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.rmi.ServerException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class LoginUtils {
    // redis缓存用户信息 使用spring进行管理
    private static RedisCache loginCache = SpringUtils.getBean(RedisCache.class);

    // 通过springBean 获得 mapper
    private static AUserMapper user = SpringUtils.getBean(AUserMapper.class);

    // 定义redis存储标识
    private static String loginKey = "loginKey";

    // 缓存过期时间（单位：秒）
    private static int expireTime = 1800; // 30分钟


    // 通过openId查询用户信息
    public static String loginByOpenId(String openId) {
        AUser aUser = user.selectAUserByOpenId(openId);
        if(aUser == null){
            aUser = new AUser();
            aUser.setNickName(aUser.getNickName());
            aUser.setHeadImg(aUser.getHeadImg());
            aUser.setOpenId(openId);
            aUser.setPhone(null);
            aUser.setRole("2");
            aUser.setCreateTime(DateUtils.getNowDate());
            aUser.setDownloadNum(0);
            user.insertAUser(aUser);
        }
        return cacheUser(aUser, "openId不存在登录失败");
    }
    // 通过手机号查询用户信息
    public static String loginByPhone(String phone) {
        AUser aUser = user.selectAUserByPhone(phone);
        return cacheUser(aUser, "手机号不存在登录失败");
    }

    private static String cacheUser(AUser aUser, String errorMsg) {
        Assert.notEmpty(aUser,()-> new ServiceException(errorMsg, HttpStatus.UNAUTHORIZED));
        // 生成UUID
        UUID uuid = UUID.randomUUID();
        //使用hash存储数据
        loginCache.setCacheMapValue(loginKey, uuid.toString(), aUser.getId());
        // 设置过期时间
        loginCache.expire(loginKey,expireTime, TimeUnit.SECONDS);
        return uuid.toString();
    }

    // 用户登录
    public static String login(String loginKey) {
        try {
            return loginByOpenId(loginKey);
        } catch (ServiceException e) {
            return loginByPhone(loginKey);
        }
    }

    // 获取用户信息
    public static AUser getUser(String uuid){
        Long id = loginCache.getCacheMapValue(loginKey, uuid);
        Assert.notEmpty(id,()->  new AccessDeniedException("用户信息不存在"));
        return LoginUtils.user.selectAUserById(id);
    }

    public static AUser getUser(){
        // 当前请求中获取Request对象
        HttpServletRequest holderRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 请求头
        String auth = holderRequest.getHeader("auth");
        Assert.notEmpty(auth,()->new AccessDeniedException("请求头参数为空"));
        return getUser(auth);
    }

    public static String loginMini(String miniOpenId) {
        try {
            return loginByMiniOpenId(miniOpenId);
        } catch (ServiceException e) {
            return loginByPhone(loginKey);
        }
    }

    public static String loginByMiniOpenId(String miniOpenId) {
        AUser aUser = user.selectUserByMiniOpenId(miniOpenId);
        if(aUser == null){
            aUser = new AUser();
            aUser.setNickName(aUser.getNickName());
            aUser.setHeadImg(aUser.getHeadImg());
            aUser.setMiniOpenId(miniOpenId);
            aUser.setPhone(null);
            aUser.setRole("2");
            aUser.setCreateTime(DateUtils.getNowDate());
            aUser.setDownloadNum(0);
            user.insertAUser(aUser);
        }
        return cacheUser(aUser, "miniOpenId不存在登录失败");
    }
}
